package cn.gemiman.daoyi.module.iot.service.equipmentmsg;

import cn.gemiman.daoyi.framework.common.pojo.PageResult;
import cn.gemiman.daoyi.framework.common.util.object.BeanUtils;
import cn.gemiman.daoyi.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.gemiman.daoyi.module.iot.controller.admin.equipmentmsg.vo.EquipmentMsgPageReqVO;
import cn.gemiman.daoyi.module.iot.controller.admin.equipmentmsg.vo.EquipmentMsgSaveReqVO;
import cn.gemiman.daoyi.module.iot.dal.dataobject.equipmentmsg.EquipmentMsgDO;
import cn.gemiman.daoyi.module.iot.dal.dataobject.jhlequipmentdevice.JhlEquipmentDeviceDO;
import cn.gemiman.daoyi.module.iot.dal.mysql.equipmentmsg.EquipmentMsgMapper;
import cn.gemiman.daoyi.module.iot.dal.mysql.jhlequipmentdevice.JhlEquipmentDeviceMapper;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;

import static cn.gemiman.daoyi.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.gemiman.daoyi.module.iot.enums.ErrorCodeConstants.EQUIPMENT_MSG_NOT_EXISTS;

/**
 * 设备消息 Service 实现类
 *
 * @author 道一源码
 */
@Service
@Validated
@Slf4j
public class EquipmentMsgServiceImpl implements EquipmentMsgService {

    @Resource
    private EquipmentMsgMapper equipmentMsgMapper;
    @Resource
    private JhlEquipmentDeviceMapper jhlEquipmentDeviceMapper;
    @Resource
    private KafkaTemplate<Object, Object> daoyiKafkaTemplate;

    @Override
    @Async
    public void msgHandler(LocalDateTime msgTime, String msg) {
        log.info("msgHandler: {}", msg);
        if (CharSequenceUtil.isBlank(msg)) {
            return;
        }
        if (JSONUtil.isTypeJSONObject(msg)) {
            // 解析kafka消息
            JSONObject obj = JSONUtil.parseObj(msg);
            if (!obj.containsKey("mac") && !obj.containsKey("deviceIdentifier")) {
                return;
            }
            if (!obj.containsKey("data")) {
                return;
            }
            String mac = obj.getStr("mac");
            String deviceIdentifier = obj.getStr("deviceIdentifier");
            if (CharSequenceUtil.isAllBlank(mac, deviceIdentifier)) {
                return;
            }
            List<JhlEquipmentDeviceDO> list = null;
            if (CharSequenceUtil.isNotBlank(mac)) {
                list = jhlEquipmentDeviceMapper.selectList(new LambdaQueryWrapperX<JhlEquipmentDeviceDO>().eq(JhlEquipmentDeviceDO::getMac, mac));
            }
            if (CollUtil.isEmpty(list) && CharSequenceUtil.isNotBlank(deviceIdentifier)) {
                list = jhlEquipmentDeviceMapper.selectList(new LambdaQueryWrapperX<JhlEquipmentDeviceDO>().eq(JhlEquipmentDeviceDO::getDeviceIdentifier, deviceIdentifier));
            }
            if (CollUtil.isEmpty(list)) {
                return;
            }
            list.forEach(deviceDO->{
                EquipmentMsgSaveReqVO saveReqVO = new EquipmentMsgSaveReqVO();
                saveReqVO.setEquipmentId(deviceDO.getId().longValue());
                saveReqVO.setEquipmentName(deviceDO.getDeviceName());
                saveReqVO.setMsgTime(msgTime);
                JSONObject data = JSONUtil.parseObj(Base64.decodeStr(obj.getStr("data")));
                saveReqVO.setMsgJson(data);
                daoyiKafkaTemplate.send("daoyi-equipment-msg", JSONUtil.toJsonStr(saveReqVO));
                if (data.containsKey("messageType")) {
                    saveReqVO.setMsgName(data.getStr("messageTypeName"));
                    saveReqVO.setMsgKey(CharSequenceUtil.format("{}_{}", "messageType", data.getStr("messageType")));
                    saveReqVO.setMsgValue(data.getStr("messageValue"));
                    createEquipmentMsg(saveReqVO);
                }
                if (data.containsKey("onlineStatus")) {
                    saveReqVO.setMsgKey("onlineStatus");
                    saveReqVO.setMsgName("上下线状态");
                    saveReqVO.setMsgValue(data.getStr("onlineStatus"));
                    createEquipmentMsg(saveReqVO);
                }
                if (data.containsKey("eventType")) {
                    saveReqVO.setMsgName(data.getStr("eventTypeName"));
                    String eventType = data.getStr("eventType");
                    String eventValue = data.getStr("eventValue");
                    if (JSONUtil.isTypeJSONObject(eventValue)) {
                        JSONObject eventValueObj = JSONUtil.parseObj(eventValue);
                        eventValueObj.keySet().forEach(key->{
                            String v = eventValueObj.getStr(key);
                            String msgKey = CharSequenceUtil.format("{}_{}_{}", "eventType", eventType, key);
                            saveReqVO.setMsgKey(msgKey);
                            if (JSONUtil.isTypeJSONArray(v)) {
                                JSONArray varr = JSONUtil.parseArray(v);
                                saveReqVO.setMsgValue(StrUtil.toString(v));
                                createEquipmentMsg(saveReqVO);
                                for (int i = 0; i < varr.size(); i++) {
                                    saveReqVO.setMsgKey(msgKey + "_" + i);
                                    Object vv = varr.get(i);
                                    saveReqVO.setMsgValue(StrUtil.toString(vv));
                                    createEquipmentMsg(saveReqVO);
                                }
                            } else {
                                saveReqVO.setMsgValue(v);
                                createEquipmentMsg(saveReqVO);
                            }
                        });
                    } else {
                        saveReqVO.setMsgKey(CharSequenceUtil.format("{}_{}", "eventType", eventType));
                        saveReqVO.setMsgValue(eventValue);
                        createEquipmentMsg(saveReqVO);
                    }
                }
            });
        }
    }

    @Override
    public Long createEquipmentMsg(EquipmentMsgSaveReqVO createReqVO) {
        // 插入
        EquipmentMsgDO equipmentMsg = BeanUtils.toBean(createReqVO, EquipmentMsgDO.class);
        equipmentMsgMapper.insert(equipmentMsg);
        // 返回
        return equipmentMsg.getId();
    }

    @Override
    public void updateEquipmentMsg(EquipmentMsgSaveReqVO updateReqVO) {
        // 校验存在
        validateEquipmentMsgExists(updateReqVO.getId());
        // 更新
        EquipmentMsgDO updateObj = BeanUtils.toBean(updateReqVO, EquipmentMsgDO.class);
        equipmentMsgMapper.updateById(updateObj);
    }

    @Override
    public void deleteEquipmentMsg(Long id) {
        // 校验存在
        validateEquipmentMsgExists(id);
        // 删除
        equipmentMsgMapper.deleteById(id);
    }

    private void validateEquipmentMsgExists(Long id) {
        if (equipmentMsgMapper.selectById(id) == null) {
            throw exception(EQUIPMENT_MSG_NOT_EXISTS);
        }
    }

    @Override
    public EquipmentMsgDO getEquipmentMsg(Long id) {
        return equipmentMsgMapper.selectById(id);
    }

    @Override
    public PageResult<EquipmentMsgDO> getEquipmentMsgPage(EquipmentMsgPageReqVO pageReqVO) {
        if (null != pageReqVO.getJhlEquipmentId()) {
            JhlEquipmentDeviceDO deviceDO = jhlEquipmentDeviceMapper.selectById(pageReqVO.getJhlEquipmentId());
            if (deviceDO != null) {
                pageReqVO.setEquipmentId(deviceDO.getId().longValue());
            }
        }
        return equipmentMsgMapper.selectPage(pageReqVO);
    }

}
